<!DOCTYPE html>
<html>

<head>
  <title>Quarkus - Working with HashiCorp Vault’s Authentication</title>
  <script id="adobe_dtm" src="https://www.redhat.com/dtm.js" type="text/javascript"></script>
  <script src="/assets/javascript/highlight.pack.js" type="text/javascript"></script>
  <META HTTP-EQUIV='Content-Security-Policy' CONTENT="default-src 'none'; script-src 'self' 'unsafe-eval' 'sha256-ANpuoVzuSex6VhqpYgsG25OHWVA1I+F6aGU04LoI+5s=' 'sha256-ipy9P/3rZZW06mTLAR0EnXvxSNcnfSDPLDuh3kzbB1w=' js.bizographics.com https://www.redhat.com assets.adobedtm.com jsonip.com https://ajax.googleapis.com https://www.googletagmanager.com https://www.google-analytics.com https://use.fontawesome.com; style-src 'self' https://fonts.googleapis.com https://use.fontawesome.com; img-src 'self' *; media-src 'self' ; frame-src https://www.googletagmanager.com https://www.youtube.com; frame-ancestors 'none'; base-uri 'none'; object-src 'none'; form-action 'none'; font-src 'self' https://use.fontawesome.com https://fonts.gstatic.com;">
  <META HTTP-EQUIV='X-Frame-Options' CONTENT="DENY">
  <META HTTP-EQUIV='X-XSS-Protection' CONTENT="1; mode=block">
  <META HTTP-EQUIV='X-Content-Type-Options' CONTENT="nosniff">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="Quarkus: Supersonic Subatomic Java">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:site" content="@QuarkusIO"> 
  <meta name="twitter:creator" content="@QuarkusIO">
  <meta property="og:url" content="https://quarkus.io/guides/vault-auth" />
  <meta property="og:title" content="Quarkus - Working with HashiCorp Vault’s Authentication" />
  <meta property="og:description" content="Quarkus: Supersonic Subatomic Java" />
  <meta property="og:image" content="/assets/images/quarkus_card.png" />
  <link rel="canonical" href="https://quarkus.io/guides/vault-auth">
  <link rel="shortcut icon" type="image/png" href="/favicon.ico" >
  <link rel="stylesheet" href="https://quarkus.io/guides/stylesheet/config.css" />
  <link rel="stylesheet" href="/assets/css/main.css" />
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
  <link rel="alternate" type="application/rss+xml"  href="https://quarkus.io/feed.xml" title="Quarkus">
  <script src="https://quarkus.io/assets/javascript/goan.js" type="text/javascript"></script>
  <script src="https://quarkus.io/assets/javascript/hl.js" type="text/javascript"></script>
</head>

<body class="guides">
  <!-- Google Tag Manager (noscript) -->
  <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NJWS5L"
  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
  <!-- End Google Tag Manager (noscript) -->

  <div class="nav-wrapper">
  <div class="grid-wrapper">
    <div class="width-12-12">
      <input type="checkbox" id="checkbox" />
      <nav id="main-nav" class="main-nav">
  <div class="container">
    <div class="logo-wrapper">
      
        <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_600px_reverse.png" class="project-logo" title="Quarkus"></a>
      
    </div>
    <label class="nav-toggle" for="checkbox">
      <i class="fa fa-bars"></i>
    </label>
    <div id="menu" class="menu">
      <span>
        <a href="/get-started/" class="">Get Started</a>
      </span>
      <span>
        <a href="/guides/" class="active">Guides</a>
      </span>
      <span>
        <a href="/community/" class="">Community</a>
      </span>
      <span>
        <a href="/support/" class="">Support</a>
      </span>
      <span>
        <a href="/blog/" class="">Blog</a>
      </span>
      <span>
        <a href="https://code.quarkus.io" class="button-cta secondary white">Start Coding</a>
      </span>
    </div>
  </div>
      </nav>
    </div>
  </div>
</div>

  <div class="content">
    <div class="guide">
  <div class="width-12-12">
    <h1 class="text-caps">Quarkus - Working with HashiCorp Vault’s Authentication</h1>
    <div class="hide-mobile toc"><ul class="sectlevel1">
<li><a href="#prerequisites">Prerequisites</a></li>
<li><a href="#token-authentication">Token Authentication</a>
<ul class="sectlevel2">
<li><a href="#client-token-using-response-wrapping">Client Token using Response Wrapping</a></li>
</ul>
</li>
<li><a href="#userpass-authentication">Userpass Authentication</a></li>
<li><a href="#approle-authentication">Approle Authentication</a>
<ul class="sectlevel2">
<li><a href="#approle-using-response-wrapping">Approle using Response Wrapping</a></li>
</ul>
</li>
<li><a href="#kubernetes-authentication">Kubernetes Authentication</a>
<ul class="sectlevel2">
<li><a href="#auth-delegator">auth-delegator</a></li>
<li><a href="#vault">Vault</a></li>
<li><a href="#deploy-the-application">Deploy the application</a></li>
</ul>
</li>
</ul></div>
    <div>
      <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Working with Vault is typically a 2 step process:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Logging in, which returns a client token</p>
</li>
<li>
<p>Start using Vault using the client token, within the limits of what is allowed by the policies associated with the token</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>There are several Vault authentication methods supported in Quarkus today, namely:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://www.vaultproject.io/docs/auth/token">Token</a>: whenever you already have a token</p>
</li>
<li>
<p><a href="https://www.vaultproject.io/docs/auth/userpass">Userpass</a>: authenticate with a username and a password</p>
</li>
<li>
<p><a href="https://www.vaultproject.io/docs/auth/approle">AppRole</a>: authenticate with a role id and a secret id (which can
be seen as a <em>Userpass</em> for automated workflows - machines and services)</p>
</li>
<li>
<p><a href="https://www.vaultproject.io/docs/auth/kubernetes">Kubernetes</a>, which is applicable to workloads deployed into Kubernetes</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>This guide aims at providing examples for each of those authentication methods.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>This technology is considered preview.</p>
</div>
<div class="paragraph">
<p>In <em>preview</em>, backward compatibility and presence in the ecosystem is not guaranteed.
Specific improvements might require to change configuration or APIs and plans to become <em>stable</em> are under way.
Feedback is welcome on our <a href="https://groups.google.com/d/forum/quarkus-dev">mailing list</a> or as issues in our <a href="https://github.com/quarkusio/quarkus/issues">GitHub issue tracker</a>.</p>
</div>
<div class="paragraph">
<p>For a full list of possible extension statuses, check our <a href="https://quarkus.io/faq/#extension-status">FAQ entry</a>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="prerequisites"><a class="anchor" href="#prerequisites"></a>Prerequisites</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To complete this guide, you need:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>to complete the <a href="vault">Vault guide</a></p>
</li>
<li>
<p>roughly 30 minutes</p>
</li>
<li>
<p>an IDE</p>
</li>
<li>
<p>JDK 1.8+ installed with <code>JAVA_HOME</code> configured appropriately</p>
</li>
<li>
<p>Apache Maven 3.6.2+</p>
</li>
<li>
<p>Docker installed</p>
</li>
<li>
<p>For the Kubernetes authentication: A Kubernetes distribution to deploy the Quarkus application (Minishift, K3s, Docker Desktop, …​)</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="token-authentication"><a class="anchor" href="#token-authentication"></a>Token Authentication</h2>
<div class="sectionbody">
<div class="paragraph">
<p>We assume there is a Vault container and a PostgreSQL container running from the <a href="vault">Vault guide</a>, and the root token is known.</p>
</div>
<div class="paragraph">
<p>First, create a new shell, <code>docker exec</code> into the container and set the root token:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">docker exec -it dev-vault sh
/ # export VAULT_TOKEN=s.5VUS8pte13RqekCB2fmMT3u2</code></pre>
</div>
</div>
<div class="paragraph">
<p>Create a token for the <code>vault-quickstart-policy</code> policy:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">/ # vault token create -policy=vault-quickstart-policy
Key                  Value
---                  -----
token                s.JqMeE1UEyUb19F6zmMW0SWx6
token_accessor       q1ynY9T7FDgbMKd3uST7RzLy
token_duration       768h
token_renewable      true
token_policies       ["default" "vault-quickstart-policy"]
identity_policies    []
policies             ["default" "vault-quickstart-policy"]</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now use the generated client token in the application configuration:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="properties" class="language-properties hljs">quarkus.vault.authentication.client-token=s.JqMeE1UEyUb19F6zmMW0SWx6</code></pre>
</div>
</div>
<div class="paragraph">
<p>Compile and start the application:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">./mvnw clean install
java -jar target/vault-quickstart-1.0-SNAPSHOT-runner.jar</code></pre>
</div>
</div>
<div class="paragraph">
<p>Finally test the application endpoint:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">curl http://localhost:8080/hello/private-key</code></pre>
</div>
</div>
<div class="paragraph">
<p>You should see: <code>123456</code>.</p>
</div>
<div class="sect2">
<h3 id="client-token-using-response-wrapping"><a class="anchor" href="#client-token-using-response-wrapping"></a>Client Token using Response Wrapping</h3>
<div class="paragraph">
<p>One drawback of this approach is that you expose a secret piece of information (i.e. the token) that can give access
to sensitive data in Vault. This requires ensuring that the application’s configuration stays secure at all time.
If an intruder was to access the client token, it would be able to start calling Vault on all endpoints permitted
by the policy.</p>
</div>
<div class="paragraph">
<p>This risk can be mitigated using an approach called
<a href="https://www.vaultproject.io/docs/concepts/response-wrapping">Response Wrapping</a> (which used to be known as
<em>Cubbyhole Authentication</em> in older versions of Vault). This principle is simple: instead of configuring the
client token itself, we hide it inside a <em>Wrapping Token</em>, which we provide to the application. Upon startup,
the application will unwrap the <em>Wrapping Token</em>, and fetch the real token from within. The additional level of
security comes from the fact that the <em>Wrapping Token</em> is short lived (from a few seconds to a few minutes;
basically just enough to start and unwrap the token), and can be unwrapped <strong>only once</strong>.
If the <em>Wrapping Token</em> gets stolen and unwrapped, we will notice immediately because the legitimate application
will get an error saying that the token is invalid.</p>
</div>
<div class="paragraph">
<p>With that in mind, let’s create a new token and wrap it inside a <em>Wrapping Token</em> with a TTL of 1 minute:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">/ # vault token create -wrap-ttl=60s -policy=vault-quickstart-policy
Key                              Value
---                              -----
wrapping_token:                  s.2cLMBoKhelDK6W3uAFT2umXu
wrapping_accessor:               ojvbOtmLzB5D47SzXGo9b3sR
wrapping_token_ttl:              1m
wrapping_token_creation_time:    2020-04-14 16:05:20.990240428 +0000 UTC
wrapping_token_creation_path:    auth/token/create
wrapped_accessor:                a4ITYQNnQtwCOUmV5DJMpCiG</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now let’s use this wrapping token in the configuration:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="properties" class="language-properties hljs">quarkus.vault.authentication.client-token-wrapping-token=s.2cLMBoKhelDK6W3uAFT2umXu</code></pre>
</div>
</div>
<div class="paragraph">
<p>Compile and run the application <strong>without the tests</strong>, you should be able now to curl the private key <code>123456</code> as before.</p>
</div>
<div class="paragraph">
<p>Stop the application, and execute tests with <code>./mvnw test</code>. They should fail with the following error:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">ERROR: Failed to start application
io.quarkus.vault.VaultException: wrapping token is not valid or does not exist; this means that the token has already expired (if so you can increase the TTL on the wrapping token) or has been consumed by somebody else (potentially indicating that the wrapping token has been stolen)</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="userpass-authentication"><a class="anchor" href="#userpass-authentication"></a>Userpass Authentication</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Normally the <code>userpass</code> auth method should already be enabled from the <a href="vault">Vault guide</a>. If not, execute the following
commands now:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">vault auth enable userpass
vault write auth/userpass/users/bob password=sinclair policies=vault-quickstart-policy</code></pre>
</div>
</div>
<div class="paragraph">
<p>And simply specify the username and password for this user in the application configuration:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="properties" class="language-properties hljs">quarkus.vault.authentication.userpass.username=bob
quarkus.vault.authentication.userpass.password=sinclair</code></pre>
</div>
</div>
<div class="paragraph">
<p>Test the application endpoint after compiling and starting the application again:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">curl http://localhost:8080/hello/private-key</code></pre>
</div>
</div>
<div class="paragraph">
<p>You should see: <code>123456</code>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Userpass supports response wrapping as well for the <code>password</code> property, although it is more
unusual to use this approach as response wrapping typically involves a technical workflow,
which is better suited for <code>approle</code>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="approle-authentication"><a class="anchor" href="#approle-authentication"></a>Approle Authentication</h2>
<div class="sectionbody">
<div class="paragraph">
<p><em>Approle</em> is an authentication method suited for technical workflows. It relies on 2 pieces of information:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>role id can be compared to the user name in <em>Userpass</em></p>
</li>
<li>
<p>secret id plays the role of the <code>password</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>To set up <em>Approle</em> you need to enable the <code>approle</code> auth method, create an app role,
and generate a role id and secret id:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">/ # vault auth enable approle
/ # vault write auth/approle/role/myapprole policies=vault-quickstart-policy

/ # vault read auth/approle/role/myapprole/role-id
Key        Value
---        -----
role_id    b15460ff-fea0-43fc-1002-a045fb60dfc4

/ # vault write -f auth/approle/role/myapprole/secret-id
Key                   Value
---                   -----
secret_id             d2f13e1f-f32a-f60a-86d8-0b5cdaeb821b
secret_id_accessor    2acff656-d049-c4b3-a752-6125e69210ba</code></pre>
</div>
</div>
<div class="paragraph">
<p>Add the appropriate properties:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="properties" class="language-properties hljs">quarkus.vault.authentication.app-role.role-id=b15460ff-fea0-43fc-1002-a045fb60dfc4
quarkus.vault.authentication.app-role.secret-id=d2f13e1f-f32a-f60a-86d8-0b5cdaeb821b</code></pre>
</div>
</div>
<div class="paragraph">
<p>After compiling and running the application you should be able to curl it on the
<code>private-key</code> endpoint to see the secret information <code>123456</code> as usual.</p>
</div>
<div class="sect2">
<h3 id="approle-using-response-wrapping"><a class="anchor" href="#approle-using-response-wrapping"></a>Approle using Response Wrapping</h3>
<div class="paragraph">
<p>Similarly to direct client token authentication, it is possible to wrap the <code>secret-id</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">/ # vault write -wrap-ttl=60s -f auth/approle/role/myapprole/secret-id
Key                              Value
---                              -----
wrapping_token:                  s.aSq7tcRqfeboZqLMPfa5gkXJ
wrapping_accessor:               u5EPZOnqyIJN8mT44od67WMS
wrapping_token_ttl:              1m
wrapping_token_creation_time:    2020-04-14 16:59:25.482352967 +0000 UTC
wrapping_token_creation_path:    auth/approle/role/myapprole/secret-id</code></pre>
</div>
</div>
<div class="paragraph">
<p>Replace the <code>secret-id</code> property with <code>secret-id-wrapping-token</code> in the configuration:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="properties" class="language-properties hljs">quarkus.vault.authentication.app-role.secret-id-wrapping-token=s.aSq7tcRqfeboZqLMPfa5gkXJ</code></pre>
</div>
</div>
<div class="paragraph">
<p>Finally, recompile the application without tests (otherwise you are going to consume the wrapping token),
launch it and curl the <code>private-key</code> endpoint. As usual, you should see <code>123456</code>.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="kubernetes-authentication"><a class="anchor" href="#kubernetes-authentication"></a>Kubernetes Authentication</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Vault provides an integration with Kubernetes to allow containers to authenticate with Vault using their
Kubernetes JWT token located in <code>/var/run/secrets/kubernetes.io/serviceaccount</code>.</p>
</div>
<div class="paragraph">
<p>The setup is more involved than with the other auth methods because we need to allow Vault to talk
to the master API to be able to validate the JWT token that the application will authenticate with.</p>
</div>
<div class="sect2">
<h3 id="auth-delegator"><a class="anchor" href="#auth-delegator"></a>auth-delegator</h3>
<div class="paragraph">
<p>The first step involves creating a <code>vault-auth-sa</code> service account with <code>auth-delegator</code>
role that Vault will use to communicate with the master API.</p>
</div>
<div class="paragraph">
<p>First create file <code>vault-auth-k8s.yml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="yaml" class="language-yaml hljs">---
apiVersion: v1
kind: ServiceAccount
metadata:
name: vault-auth-sa
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: vault-auth-delegator
subjects:
- kind: User
name: vault-auth-sa
namespace: default
roleRef:
kind: ClusterRole
name: system:auth-delegator
apiGroup: rbac.authorization.k8s.io</code></pre>
</div>
</div>
<div class="paragraph">
<p>And apply it: <code>kubectl apply -f vault-auth-k8s.yml</code>.</p>
</div>
<div class="paragraph">
<p>Once the objects are created, we need to capture the JWT token of this service account,
and grab the public certificate of the cluster:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">secret_name=$(kubectl get sa vault-auth-sa -o json | jq -r '.secrets[0].name')
token=$(kubectl get secret $secret_name -o json | jq -r '.data.token' | base64 --decode)
echo token=$token
kubectl get secret $secret_name -o json | jq -r '.data."ca.crt"' | base64 -D &gt; /tmp/ca.crt</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="vault"><a class="anchor" href="#vault"></a>Vault</h3>
<div class="paragraph">
<p>The next step requires to exec interactively with the root token into the Vault container
to configure the Kubernetes auth method:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">docker exec -it dev-vault sh
export VAULT_TOKEN=s.5VUS8pte13RqekCB2fmMT3u2</code></pre>
</div>
</div>
<div class="paragraph">
<p>Once inside the pod, set the token variable to the value that was just printed in the console before, and
recreate <code>ca.crt</code> with the same content as <code>/tmp/ca.crt</code> outside the container. Finally use <code>kubectl config view</code>
to assess the url of your Kubernetes cluster:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">token=...       =&gt; set the value printed in the console just before
vi ca.crt       =&gt; copy/paste /tmp/ca.crt from outside the container
kubernetes_host =&gt; url from the kubectl config view (e.g. https://kubernetes.docker.internal:6443)</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now we have all the information we need to configure Vault:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">vault auth enable kubernetes

# configure master API access from Vault
vault write auth/kubernetes/config \
    token_reviewer_jwt=$token \
    kubernetes_host=$kubernetes_host \
    kubernetes_ca_cert=@ca.crt

# create vault-quickstart-role role
vault write auth/kubernetes/role/vault-quickstart-role \
    bound_service_account_names=vault-quickstart-sa \
    bound_service_account_namespaces=default \
    policies=vault-quickstart-policy \
    ttl=1h</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="deploy-the-application"><a class="anchor" href="#deploy-the-application"></a>Deploy the application</h3>
<div class="paragraph">
<p>Add the following properties to the application (and remove any other authentication Vault property,
plus replace <code>&lt;host&gt;</code> by the ip or name of the local host that is running the Vault and PostgreSQL containers,
such that they will be accessible from the pod):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="properties" class="language-properties hljs">quarkus.vault.url=http://&lt;host&gt;:8200
quarkus.datasource.url = jdbc:postgresql://&lt;host&gt;:5432/mydatabase

quarkus.vault.authentication.kubernetes.role=vault-quickstart-role

quarkus.log.category."io.quarkus.vault".level=DEBUG</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now build the application:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">./mvnw package -DskipTests
docker build -f src/main/docker/Dockerfile.jvm -t quarkus/vault-quickstart-jvm .</code></pre>
</div>
</div>
<div class="paragraph">
<p>Create a <code>vault-quickstart-k8s.yml</code> file with:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="yaml" class="language-yaml hljs">---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: vault-quickstart-sa
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: vaultapp
  name: vaultapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: vaultapp
  template:
    metadata:
      labels:
        app: vaultapp
    spec:
      serviceAccountName: vault-quickstart-sa
      containers:
      - image: quarkus/vault-quickstart-jvm
        imagePullPolicy: Never
        name: vaultapp
        ports:
        - containerPort: 8080
          name: vaultport
          protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: vaultapp
  labels:
    app: vaultapp
spec:
  type: NodePort
  ports:
    - name: vault
      port: 8080
      nodePort: 30400
  selector:
    app: vaultapp</code></pre>
</div>
</div>
<div class="paragraph">
<p>And apply it: <code>kubectl apply -f vault-quickstart-k8s.yml</code>.</p>
</div>
<div class="paragraph">
<p>This will deploy the application, and make it available on port <code>30400</code> of the Kubernetes host.</p>
</div>
<div class="paragraph">
<p>You can check that the application has started from the logs:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">kubectl get pods
pod=$(kubectl get pod -l app=vaultapp -o json | jq -r '.items[0].metadata.name')
kubectl logs $pod</code></pre>
</div>
</div>
<div class="paragraph">
<p>You should see:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">exec java -Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager -XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:MinHeapFreeRatio=20 -XX:MaxHeapFreeRatio=40 -XX:+ExitOnOutOfMemoryError -cp . -jar /deployments/app.jar
__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,&lt; / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2020-04-15 18:30:00,983 DEBUG [io.qua.vau.run.con.VaultConfigSource] (main) loaded vault runtime config VaultRuntimeConfig{url=Optional[http://&lt;host&gt;:8200], kubernetesAuthenticationRole=vault-quickstart-role, kubernetesJwtTokenPath='/var/run/secrets/kubernetes.io/serviceaccount/token', userpassUsername='', userpassPassword='***', appRoleRoleId='', appRoleSecretId='***', appRoleSecretIdWrappingToken='***', clientToken=***, clientTokenWrappingToken=***, renewGracePeriod=PT1H, cachePeriod=PT10M, logConfidentialityLevel=MEDIUM, kvSecretEngineVersion=2, kvSecretEngineMountPath='secret', tlsSkipVerify=false, tlsCaCert=Optional.empty, connectTimeout=PT5S, readTimeout=PT1S}
2020-04-15 18:30:00,985 DEBUG [io.qua.vau.run.con.VaultConfigSource] (main) loaded vault buildtime config io.quarkus.vault.runtime.config.VaultBuildTimeConfig@4163f1cd
2020-04-15 18:30:01,310 DEBUG [io.qua.vau.run.cli.OkHttpClientFactory] (main) create SSLSocketFactory with tls /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
2020-04-15 18:30:01,559 DEBUG [io.qua.vau.run.VaultAuthManager] (main) authenticate with jwt at: /var/run/secrets/kubernetes.io/serviceaccount/token =&gt; ***
2020-04-15 18:30:01,779 DEBUG [io.qua.vau.run.VaultAuthManager] (main) created new login token: {clientToken: ***, renewable: true, leaseDuration: 3600s, valid_until: Wed Apr 15 19:30:01 GMT 2020}
2020-04-15 18:30:01,802 DEBUG [io.qua.vau.run.con.VaultConfigSource] (main) loaded 1 properties from vault
2020-04-15 18:30:02,722 DEBUG [io.qua.vau.run.VaultAuthManager] (Agroal_7305849841) extended login token: {clientToken: ***, renewable: true, leaseDuration: 3600s, valid_until: Wed Apr 15 19:30:02 GMT 2020}
2020-04-15 18:30:03,274 INFO  [io.quarkus] (main) vault-quickstart 1.0-SNAPSHOT (powered by Quarkus 999-SNAPSHOT) started in 4.255s. Listening on: http://0.0.0.0:8080
2020-04-15 18:30:03,276 INFO  [io.quarkus] (main) Profile prod activated.
2020-04-15 18:30:03,276 INFO  [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, jdbc-postgresql, narayana-jta, resteasy, vault]</code></pre>
</div>
</div>
<div class="paragraph">
<p>Notice in particular the following log line:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">authenticate with jwt at: /var/run/secrets/kubernetes.io/serviceaccount/token =&gt; ***</code></pre>
</div>
</div>
<div class="paragraph">
<p>Finally curl the <code>private-key</code> endpoint to make sure you can retrieve your secret:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">curl http://localhost:30400/hello/private-key</code></pre>
</div>
</div>
<div class="paragraph">
<p>You should see <code>123456</code>.</p>
</div>
</div>
</div>
</div>
    </div>
  </div>
</div>

  </div>

  <div class="content project-footer">
  <div class="footer-section">
    <div class="logo-wrapper">
      <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_reverse.svg" class="project-logo" title="Quarkus"></a>
    </div>
  </div>
  <div class="grid-wrapper">
    <p class="grid__item width-3-12">Quarkus is open. All dependencies of this project are available under the <a href='https://www.apache.org/licenses/LICENSE-2.0' target='_blank'>Apache Software License 2.0</a> or compatible license.<br /><br />This website was built with <a href='https://jekyllrb.com/' target='_blank'>Jekyll</a>, is hosted on <a href='https://pages.github.com/' target='_blank'>Github Pages</a> and is completely open source. If you want to make it better, <a href='https://github.com/quarkusio/quarkusio.github.io' target='_blank'>fork the website</a> and show us what you’ve got.</p>

    
      <div class="width-1-12 project-links">
        <span>Navigation</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="/">Home</a></li>
          
            <li><a href="/guides">Guides</a></li>
          
            <li><a href="/community/#contributing">Contribute</a></li>
          
            <li><a href="/faq">FAQ</a></li>
          
            <li><a href="/get-started">Get Started</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Contribute</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://twitter.com/quarkusio">Follow us</a></li>
          
            <li><a href="https://github.com/quarkusio">GitHub</a></li>
          
            <li><a href="/security">Security&nbsp;policy</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Get Help</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://groups.google.com/forum/#!forum/quarkus-dev">Forums</a></li>
          
            <li><a href="https://quarkusio.zulipchat.com">Chatroom</a></li>
          
        </ul>
      </div>
    

    
      <div class="width-3-12 more-links">
        <span>Quarkus is made of community projects</span>
        <ul class="footer-links">
          
            <li><a href="https://vertx.io/" target="_blank">Eclipse Vert.x</a></li>
          
            <li><a href="https://microprofile.io" target="_blank">Eclipse MicroProfile</a></li>
          
            <li><a href="https://hibernate.org" target="_blank">Hibernate</a></li>
          
            <li><a href="https://netty.io" target="_blank">Netty</a></li>
          
            <li><a href="https://resteasy.github.io" target="_blank">RESTEasy</a></li>
          
            <li><a href="https://camel.apache.org" target="_blank">Apache Camel</a></li>
          
            <li><a href="https://code.quarkus.io/" target="_blank">And many more...</a></li>
          
        </ul>
      </div>
    
  </div>
</div>
  <div class="content redhat-footer">
  <div class="grid-wrapper">
    <span class="licence">
      <i class="fab fa-creative-commons"></i><i class="fab fa-creative-commons-by"></i> <a href="https://creativecommons.org/licenses/by/3.0/" target="_blank">CC by 3.0</a> | <a href="https://www.redhat.com/en/about/privacy-policy">Privacy Policy</a>
    </span>
    <span class="redhat">
      Sponsored by
    </span>
    <span class="redhat-logo">
      <a href="https://www.redhat.com/" target="_blank"><img src="/assets/images/redhat_reversed.svg"></a>
    </span>
  </div>
</div>


  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" integrity="sha384-8gBf6Y4YYq7Jx97PIqmTwLPin4hxIzQw5aDmUg/DDhul9fFpbbLcLh3nTIIDJKhx" crossorigin="anonymous"></script>
  <script type="text/javascript" src="/assets/javascript/mobile-nav.js"></script>
  <script type="text/javascript" src="/assets/javascript/scroll-down.js"></script>
  <script src="/assets/javascript/satellite.js" type="text/javascript"></script>
  <script src="https://quarkus.io/guides/javascript/config.js" type="text/javascript"></script>
  <script src="/assets/javascript/search-filter.js" type="text/javascript"></script>
  <script src="/assets/javascript/back-to-top.js" type="text/javascript"></script>
</body>

</html>
